/*
 * Copyright 1992-4   BG Systems, Inc.
 * open_lv.c
 *
 * routines that are to be called to open & close the LV824
 *
 * Author         Date       Comments
 * John Green     21-Oct-94  Created from fblib.c
 * John Green     01-Feb-95  Final touches for relase of 3.0
 * John Green     13-Feb-97  Win32
 */

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "lv3.h"

extern int init_lv(bglv *);
extern int check_rev(bglv *);
// extern void ErrorHandler(char *, DWORD );

RS_ERR rs_err;
HANDLE comHandle1;
HANDLE comHandle2;
DCB dcb1, dcb2;

int set_baud(int, int);
void set_dcb(DCB *, COMMTIMEOUTS *);
void set_pc_baud(DCB *, int);

int open_lv(bglv *bgp, char *p, int flag)
{
   int  st;

   BOOL success;
   COMMTIMEOUTS timeouts1, timeouts2;

   if ( strncmp(p, "COM1", 4) == 0)
   {
      bgp->sp_fd = 1;
      comHandle1 = CreateFile("COM1", GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
      if ( comHandle1 == INVALID_HANDLE_VALUE)
         return(-1);

      success = GetCommState(comHandle1, &dcb1);
      if ( !success )
		  return(-1);
      set_dcb(&dcb1, &timeouts1);
      success = SetCommState(comHandle1, &dcb1);
   	  SetCommTimeouts(comHandle1, &timeouts1);
   }
   else if ( strncmp(p, "COM2", 4) == 0 )
   {
      bgp->sp_fd = 2;
      comHandle2 = CreateFile("COM2", GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
	  if ( comHandle2 == INVALID_HANDLE_VALUE)
         return(-1);

      success = GetCommState(comHandle2, &dcb2);
      set_dcb(&dcb2, &timeouts2);
      success = SetCommState(comHandle2, &dcb2);
      SetCommTimeouts(comHandle2, &timeouts2);
   }

   if (!success)
		return(-1);

   rs_err.wrt = 0;
   rs_err.rd = 0;
   rs_err.len = 0;
   rs_err.nl = 0;
   rs_err.cycles = 0;
   rs_err.thou = 0;

/*
 * Initialize port.
 */

    ////DN we always run the flybox on 115.2K, so likely to find it in that state, try first
	st = set_baud(bgp->sp_fd, BAUD1152);
	st = check_rev(bgp);


    ////Shuda, DN: for if the flybox wasn't closed properly, baud rate might not be 19.2K - try all baudrates
	if( st < 0 )
	{
		st = set_baud(bgp->sp_fd, BAUD192);
		st = check_rev(bgp);
		if( st < 0 )
		{
			st = set_baud(bgp->sp_fd, BAUD576);
			st = check_rev(bgp);
			if( st < 0 )
			{
				st = set_baud(bgp->sp_fd, BAUD384);
				st = check_rev(bgp);
				if( st < 0 )
				{
					st = set_baud(bgp->sp_fd, BAUD96);
					st = check_rev(bgp);
					if( st < 0 )
					{
						st = set_baud(bgp->sp_fd, BAUD48);
						st = check_rev(bgp);
						if( st < 0 )
						{
							st = set_baud(bgp->sp_fd, BAUD24);
							st = check_rev(bgp);
						}
					}
				}
			}
		}
	}
	////end Shuda

	if ( st < 0 )
		return(st);
	else
		return(0);
}

int set_baud(int sp_fd, int b)
{
   int st;

   if ( sp_fd == 1 )
   {
      set_pc_baud(&dcb1, b);
      st = SetCommState(comHandle1, &dcb1);
   }
   else if ( sp_fd == 2)
   {
      set_pc_baud(&dcb2, b);
      st = SetCommState(comHandle2, &dcb2);
   }
   if (!st)
      return(-1);

	return(st);
}

void close_lv(bglv *bgp)
{
  int att;
  int st;

  //bgp->baud = BAUD192;
  bgp->baud = BAUD1152; // DN: we always run at 115.2 kbps
  st = init_lv(bgp);

  att = 1000*rs_err.thou + rs_err.cycles;
  CloseHandle(comHandle1);

//  close(bgp->sp_fd);
#ifdef _DEBUG  // DN: I don't want to see this output in release mode
  printf("\nRead Attempts:  %d\n", att);
  printf("\nErrors Detected\n");
  printf("Read        Write    \n");
  printf("%5d      %5d     \n",rs_err.rd, rs_err.wrt);
#endif // _DEBUG

  Sleep(1000);
}

void set_dcb(DCB *dcb, COMMTIMEOUTS *timeout )
{
   dcb->BaudRate = 19200;
   dcb->ByteSize = 8;
   dcb->Parity   = NOPARITY;
   dcb->StopBits = ONESTOPBIT;

   dcb->XonChar = 11;
   dcb->XoffChar = 13;
   dcb->fOutX = TRUE;
   dcb->fInX  = TRUE;

   dcb->fOutxCtsFlow = FALSE;
   dcb->fOutxDsrFlow = FALSE;

   timeout->ReadIntervalTimeout = MAXDWORD;
   timeout->ReadTotalTimeoutMultiplier = 0;
   timeout->ReadTotalTimeoutConstant   = 0;
   timeout->WriteTotalTimeoutMultiplier = 0;
   timeout->WriteTotalTimeoutConstant   = 0;
   
}

void set_pc_baud(DCB *dcb, int b)
{
	switch(b & 0x70)
	{
	 case BAUD24:
		dcb->BaudRate = 2400;
		break;
	 case BAUD48:
		dcb->BaudRate = 4800;
		break;
	 case BAUD96:
		dcb->BaudRate = 9600;
		break;
	 case BAUD192:
		dcb->BaudRate = 19200;
		break;
	 case BAUD384:
		dcb->BaudRate = 38400;
		break;
	 case BAUD576:
		dcb->BaudRate = 57600;
		break;
	 case BAUD1152:
		dcb->BaudRate = 115200;
		break;
	}

}
